home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 4 / Assassins 4 (1999)(Weird Science).iso / misc / omega / source / command2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-02  |  29.4 KB  |  1,213 lines

  1. /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
  2. /* command2.c */
  3.  
  4. /* This file contains toplevel commands called from command1.c */
  5.  
  6. #ifndef MSDOS
  7. #include <unistd.h>
  8. #include <ctype.h>
  9. #endif
  10.  
  11. #include "glob.h"
  12.  
  13. /* no op a turn.... */
  14. void rest()
  15. {
  16.   if (random_range(20) == 1) {
  17.     switch(random_range(10)) {
  18.       case 0: print3(" Time passes slowly.... "); break;
  19.       case 1: print3(" Tick. Tock. Tick. Tock. "); break;
  20.       case 2: print3(" Ho Hum. "); break;
  21.       case 3: print3(" Beauty Sleep. Well, in your case, Ugly Sleep. "); break;
  22.       case 4: print3(" And with Strange Aeons, even Death may die. "); break;
  23.       case 5: print3(" La Di Da. "); break;
  24.       case 6: print3(" Time keeps on tickin' tickin' -- into the future.... ");
  25.             break;
  26.       case 7: print3(" Boooring! "); break;
  27.       case 8: print3(" You think I like watching you sleep? "); break;
  28.       case 9: print3(" You sure have an early bedtime! "); break;
  29.     }
  30.     morewait();
  31.   }
  32. }
  33.  
  34.  
  35. /* read a scroll, book, tome, etc. */
  36. void peruse()
  37. {
  38.   int index;
  39.   struct object *obj;
  40.  
  41.   clearmsg();
  42.  
  43.   if (Player.status[BLINDED] > 0)
  44.     print3("You're blind -- you can't read!!!");
  45.   else if (Player.status[AFRAID] > 0)
  46.     print3("You are too afraid to stop to read a scroll!");
  47.   else {
  48.     print1("Read -- ");
  49.     index = getitem(SCROLL);
  50.     if (index == ABORT)
  51.       setgamestatus(SKIP_MONSTERS);
  52.     else {
  53.       obj = Player.possessions[index];
  54.       if (obj->objchar != SCROLL) {
  55.     print3("There's nothing written on ");
  56.     nprint3(itemid(obj));
  57.       }
  58.       else {
  59.     nprint1("You carefully unfurl the scroll....");
  60.     morewait();
  61.     item_use(obj);
  62.     dispose_lost_objects(1,obj);
  63.       }
  64.     }
  65.   }
  66. }
  67.  
  68.  
  69.  
  70.  
  71. void quaff()
  72. {
  73.   int index;
  74.   struct object *obj;
  75.   clearmsg();
  76.   print1("Quaff --");
  77.   index = getitem(POTION);
  78.   if (index == ABORT)
  79.     setgamestatus(SKIP_MONSTERS);
  80.   else {
  81.     obj = Player.possessions[index];
  82.     if (obj->objchar != POTION) {
  83.       print3("You can't drink ");
  84.       nprint3(itemid(obj));
  85.     }
  86.     else {
  87.       print1("You drink it down.... ");
  88.       item_use(obj);
  89.       morewait();
  90.       dispose_lost_objects(1,obj);
  91.     }
  92.   }
  93. }
  94.  
  95.  
  96.  
  97.  
  98. void activate()
  99. {
  100.   int index;
  101.   char response;
  102.  
  103.   clearmsg();
  104.  
  105.   print1("Activate -- item [i] or artifact [a] or quit [ESCAPE]?");
  106.   do response = (char) mcigetc();
  107.   while ((response != 'i') && (response != 'a') && (response != ESCAPE));
  108.   if (response != ESCAPE) {
  109.     if (response == 'i')
  110.       index = getitem(THING);
  111.     else if (response == 'a')
  112.       index = getitem(ARTIFACT);
  113.     if (index != ABORT) {
  114.       clearmsg();
  115.       print1("You activate it.... ");
  116.       morewait();
  117.       item_use(Player.possessions[index]);
  118.     }
  119.     else setgamestatus(SKIP_MONSTERS);
  120.   }
  121.   else setgamestatus(SKIP_MONSTERS);
  122. }
  123.  
  124.  
  125.  
  126.  
  127.  
  128. void eat()
  129. {
  130.   int index;
  131.   struct object *obj;
  132.  
  133.   clearmsg();
  134.  
  135.   print1("Eat --");
  136.   index = getitem(FOOD);
  137.   if (index == ABORT)
  138.     setgamestatus(SKIP_MONSTERS);
  139.   else {
  140.     obj = Player.possessions[index];
  141.     if ((obj->objchar != FOOD)&&(obj->objchar != CORPSE)) {
  142.       print3("You can't eat ");
  143.       nprint3(itemid(obj));
  144.     }
  145.     else {
  146.       if (obj->usef == I_FOOD) Player.food = max(0,Player.food+obj->aux);
  147.       item_use(obj);
  148.       dispose_lost_objects(1,obj);
  149.       if (Current_Dungeon == E_COUNTRYSIDE) {
  150.     Time += 100;
  151.     hourly_check();
  152.       }
  153.     }
  154.   }
  155.   foodcheck();
  156. }
  157.  
  158.  
  159.  
  160.  
  161. /* search all adjacent spots for secrecy */
  162. void search(searchval)
  163. int *searchval;
  164. {
  165.   int i;
  166.   if (Player.status[AFRAID] > 0)
  167.     print3("You are too terror-stricken to stop to search for anything.");
  168.   else {
  169.     if (!gamestatusp(FAST_MOVE)) {
  170.       setgamestatus(FAST_MOVE);
  171.       *searchval = Searchnum;
  172.     }
  173.     for (i=0;i<9;i++) 
  174.       searchat(Player.x+Dirs[0][i],Player.y+Dirs[1][i]);
  175.     drawvision(Player.x,Player.y);
  176.   }
  177. }
  178.  
  179.  
  180.  
  181. /* pick up a thing where the player is */
  182.  void pickup()
  183.  {
  184.    if (Level->site[Player.x][Player.y].things == NULL)
  185.      print3("There's nothing there!");
  186.    else if (Player.status[SHADOWFORM])
  187.      print3("You can't really interact with the real world in your shadowy state.");
  188.    else
  189.      pickup_at(Player.x,Player.y);
  190.  }
  191.  
  192.  
  193. #ifndef MSDOS
  194. /* floor inventory */
  195. void floor_inv()
  196. {
  197.   pol ol = Level->site[Player.x][Player.y].things;
  198.   setgamestatus(SKIP_MONSTERS);
  199.   menuclear();
  200.   while (ol != NULL) {
  201.     if (ol->thing == NULL) print3("***Error; null thing on things list***");
  202.     else {
  203.       menuprint(itemid(ol->thing));
  204.       menuprint("\n");
  205.     }
  206.     ol = ol->next;
  207.   }
  208.   showmenu();
  209.   morewait();
  210.   xredraw();
  211. }
  212. #endif
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222. void drop()
  223. {
  224.   int index,n;
  225.   
  226.   clearmsg();
  227.  
  228.   print1("Drop --");
  229.   index = getitem(CASH);
  230.   if (index == ABORT)
  231.     setgamestatus(SKIP_MONSTERS);
  232.   else {
  233.     if (index == CASHVALUE) drop_money();
  234.     else if ((! Player.possessions[index]->used) ||
  235.          (! cursed(Player.possessions[index]))) {
  236.       if (Player.possessions[index]->number == 1) {
  237.     p_drop_at(Player.x,Player.y,1,Player.possessions[index]);
  238.     conform_lost_objects(1,Player.possessions[index]);
  239.       }
  240.       else {
  241.     n = getnumber(Player.possessions[index]->number);
  242.     p_drop_at(Player.x,Player.y,n,Player.possessions[index]);
  243.     conform_lost_objects(n,Player.possessions[index]);
  244.       }
  245.     }
  246.     else {
  247.       print3("You can't seem to get rid of: ");
  248.       nprint3(itemid(Player.possessions[index]));
  249.     }
  250.   }
  251.   calc_melee();
  252. }
  253.  
  254.  
  255.       
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262. /* talk to the animals -- learn their languages.... */
  263. void talk()
  264. {
  265.   int dx,dy,index=0;
  266.   char response;
  267.   struct monster *m;
  268.  
  269.   clearmsg();
  270.  
  271.   print1("Talk --");
  272.   index = getdir();
  273.  
  274.   if (index == ABORT)
  275.     setgamestatus(SKIP_MONSTERS);
  276.   else {
  277.     dx = Dirs[0][index];
  278.     dy = Dirs[1][index];
  279.     
  280.     if ((! inbounds(Player.x+dx, Player.y+dy)) ||
  281.     (Level->site[Player.x+dx][Player.y+dy].creature == NULL)) {
  282.       print3("There's nothing there to talk to!!!");
  283.       setgamestatus(SKIP_MONSTERS);
  284.     }
  285.     else {
  286.       m = Level->site[Player.x+dx][Player.y+dy].creature;
  287.       menuclear();
  288.       strcpy(Str1,"     Talk to ");
  289.       strcat(Str1,m->monstring);
  290.       strcat(Str1,":");
  291.       menuprint(Str1);
  292.       menuprint("\na: Greet.");
  293.       menuprint("\nb: Threaten.");
  294.       menuprint("\nc: Surrender.");
  295.       menuprint("\nESCAPE: Clam up.");
  296.       showmenu();
  297.       do response = menugetc();
  298.       while ((response != 'a') &&
  299.          (response != 'b') &&
  300.          (response != 'c') &&
  301.          (response != ESCAPE));
  302.       switch(response) {
  303.       case 'a': monster_talk(m); break;
  304.       case 'b': threaten(m); break;
  305.       case 'c': surrender(m); break;
  306.       default: setgamestatus(SKIP_MONSTERS); break;
  307.       }
  308.     }
  309.   }
  310.   xredraw();
  311. }
  312.  
  313. /* try to deactivate a trap */
  314. void disarm()
  315. {
  316.   int x,y,index=0;
  317.   pob o;
  318.  
  319.   clearmsg();
  320.   print1("Disarm -- ");
  321.  
  322.   index = getdir();
  323.  
  324.   if (index == ABORT)
  325.     setgamestatus(SKIP_MONSTERS);
  326.   else {
  327.     x = Dirs[0][index]+Player.x;
  328.     y = Dirs[1][index]+Player.y;
  329.     
  330.     if (! inbounds(x,y))
  331.       print3("Whoa, off the map...");
  332.     else if (Level->site[x][y].locchar != TRAP)
  333.       print3("You can't see a trap there!");
  334.     else {
  335.       if (random_range(50+difficulty()*5) < 
  336.       Player.dex*2+Player.level*3+Player.rank[THIEVES]*10) {
  337.     print1("You disarmed the trap!");
  338.     if (random_range(100) < Player.dex+Player.rank[THIEVES]*10) {
  339.       o = ((pob) checkmalloc(sizeof(objtype)));
  340.       switch(Level->site[x][y].p_locf) {
  341.       case L_TRAP_DART: 
  342.         *o=Objects[THINGID+17];
  343.         break;
  344.       case L_TRAP_DISINTEGRATE:
  345.         *o=Objects[THINGID+23];
  346.         break;
  347.       case L_TRAP_SLEEP_GAS:
  348.         *o=Objects[THINGID+22];
  349.         break;
  350.       case L_TRAP_TELEPORT:
  351.         *o=Objects[THINGID+21];
  352.         break;
  353.       case L_TRAP_ABYSS:
  354.         *o=Objects[THINGID+24];
  355.         break;
  356.       case L_TRAP_FIRE:
  357.         *o=Objects[THINGID+20];
  358.         break;
  359.       case L_TRAP_SNARE:
  360.         *o=Objects[THINGID+19];
  361.         break;
  362.       case L_TRAP_ACID:
  363.         *o=Objects[THINGID+18];
  364.         break;
  365.       case L_TRAP_MANADRAIN:
  366.         *o=Objects[THINGID+25];
  367.         break;
  368.       default:
  369.         free(o);
  370.         o = NULL;
  371.         break;
  372.       }
  373.       if (o != NULL) {
  374.         print2("You manage to retrieve the trap components!");
  375.         morewait();
  376.         Objects[o->id].known = 1;
  377.         o->known = 1;
  378.         gain_item(o);
  379.         gain_experience(25);
  380.       }
  381.     }
  382.     Level->site[x][y].p_locf = L_NO_OP;
  383.     Level->site[x][y].locchar = FLOOR;
  384.     lset(x, y, CHANGED);
  385.     gain_experience(5);
  386.       }
  387.       else if (random_range(10+difficulty()*2) > Player.dex) {
  388.     print1("You accidentally set off the trap!");
  389.     Player.x = x; Player.y = y;
  390.     p_movefunction(Level->site[x][y].p_locf);
  391.       }
  392.       else print1("You failed to disarm the trap.");
  393.     }
  394.   }
  395. }
  396.  
  397. /* is it more blessed to give, or receive? */
  398. void give()
  399. {
  400.   int index;
  401.   int dx,dy,dindex=0;
  402.   struct monster *m;
  403.   pob obj;
  404.  
  405.   clearmsg();
  406.  
  407.   print1("Give to monster --");
  408.   dindex = getdir();
  409.   if (dindex == ABORT) 
  410.     setgamestatus(SKIP_MONSTERS);
  411.   else {
  412.     dx = Dirs[0][dindex];
  413.     dy = Dirs[1][dindex];
  414.     if (! inbounds(Player.x+dx, Player.y+dy))
  415.       print3("Whoa, off the map...");
  416.     else if (Level->site[Player.x+dx][Player.y+dy].creature == NULL) {
  417.       print3("There's nothing there to give something to!!!");
  418.       setgamestatus(SKIP_MONSTERS);
  419.     }
  420.     else {
  421.       m = Level->site[Player.x+dx][Player.y+dy].creature;
  422.       clearmsg();
  423.       print1("Give what? "); 
  424.       index = getitem(CASH);
  425.       if (index == ABORT)
  426.     setgamestatus(SKIP_MONSTERS);
  427.       else if (index == CASHVALUE) give_money(m);
  428.       else if (! cursed(Player.possessions[index])) {
  429.     obj = ((pob) checkmalloc(sizeof(objtype)));
  430.     *obj = *(Player.possessions[index]);
  431.     obj->used = FALSE;
  432.     conform_lost_objects(1,Player.possessions[index]);
  433.     obj->number = 1;
  434.     givemonster(m,obj);
  435.     print2("Given: ");
  436.     nprint2(itemid(obj));
  437.     morewait();
  438.     calc_melee();
  439.       }
  440.       else {
  441.     print3("You can't even give away: ");
  442.     nprint3(itemid(Player.possessions[index]));
  443.       }
  444.     }
  445.   }
  446. }
  447.  
  448.  
  449.  
  450.  
  451. /* zap a wand, of course */
  452. void zapwand()
  453. {
  454.   int index;
  455.   struct object *obj;
  456.  
  457.   clearmsg();
  458.  
  459.   if (Player.status[AFRAID] > 0)
  460.     print3("You are so terror-stricken you can't hold a wand straight!");
  461.   else {
  462.     print1("Zap --");
  463.     index = getitem(STICK);
  464.     if (index == ABORT)
  465.       setgamestatus(SKIP_MONSTERS);
  466.     else {
  467.       obj = Player.possessions[index];
  468.       if (obj->objchar != STICK) {
  469.     print3("You can't zap: ");
  470.     nprint3(itemid(obj));
  471.       }
  472.       else 
  473.     if (obj->charge < 1) 
  474.       print3("Fizz.... Pflpt. Out of charges. ");
  475.     else {
  476.       obj->charge--;
  477.       item_use(obj);
  478.     }
  479.     }
  480.   }
  481. }
  482.  
  483. /* cast a spell */
  484. void magic()
  485. {
  486.   int index,drain;
  487.   clearmsg();
  488.   if (Player.status[AFRAID] > 0)
  489.     print3("You are too afraid to concentrate on a spell!");
  490.   else {
  491.     index = getspell();
  492.     xredraw();
  493.     if (index == ABORT)
  494.       setgamestatus(SKIP_MONSTERS);
  495.     else {
  496.       drain = Spells[index].powerdrain;
  497.       if (Lunarity == 1) drain = drain / 2;
  498.       else if (Lunarity == -1) drain = drain *2;
  499.       if (drain > Player.mana)
  500.     if (Lunarity == -1 && Player.mana >= drain/2)
  501.       print3("The contrary moon has made that spell too draining! ");
  502.     else
  503.       print3("You lack the power for that spell! ");
  504.       else {
  505.     Player.mana -= drain;
  506.     cast_spell(index);
  507.       }
  508.     }
  509.   }
  510.   dataprint();
  511. }
  512.  
  513.  
  514. /* go upstairs ('<' command) */
  515. void upstairs()
  516. {
  517.   if (Level->site[Player.x][Player.y].locchar != STAIRS_UP)
  518.     print3("Not here!");
  519.   else if (Level->site[Player.x][Player.y].p_locf == L_ESCALATOR)
  520.     p_movefunction(Level->site[Player.x][Player.y].p_locf);
  521.   else {
  522.     if (gamestatusp(MOUNTED))
  523.       print2("You manage to get your horse upstairs.");
  524.     print1("You ascend a level.");
  525.     if (Level->depth <= 1) {
  526.       if (Level->environment == E_SEWERS)
  527.     change_environment(E_CITY);
  528.       else change_environment(E_COUNTRYSIDE);
  529.     }
  530.     else change_level(Level->depth,Level->depth-1,FALSE);
  531.     roomcheck();
  532.   }
  533.   setgamestatus(SKIP_MONSTERS);
  534. }
  535.  
  536.  
  537.  
  538. /* go downstairs ('>' command) */
  539. void downstairs()
  540. {
  541.   if (Level->site[Player.x][Player.y].locchar != STAIRS_DOWN)
  542.     print3("Not here!");
  543.   else if (Level->site[Player.x][Player.y].p_locf == L_ENTER_CIRCLE ||
  544.     Level->site[Player.x][Player.y].p_locf == L_ENTER_COURT)
  545.     p_movefunction(Level->site[Player.x][Player.y].p_locf);
  546.   else {
  547.     if (gamestatusp(MOUNTED))
  548.       print2("You manage to get your horse downstairs.");
  549.     if (Current_Environment == Current_Dungeon) {
  550.       print1("You descend a level.");
  551.       change_level(Level->depth,Level->depth+1,FALSE);
  552.       roomcheck();
  553.     }
  554.     else if ((Current_Environment == E_CITY) ||
  555.          (Last_Environment == E_CITY))
  556.       change_environment(E_SEWERS);
  557.     else if (Current_Environment != Current_Dungeon)
  558.       print3("This stairway is deviant. You can't use it.");
  559.   }
  560.   setgamestatus(SKIP_MONSTERS);
  561. }
  562.  
  563.  
  564.  
  565.  
  566. /* set various player options */
  567. /* have to redefine in odefs for next full recompile */
  568. void setoptions()
  569. {
  570.   int slot = 1,to,done = FALSE;
  571.   int response;
  572.  
  573.   clearmsg();
  574.   menuclear();
  575.  
  576.   display_options();
  577.  
  578.   move_slot(1,1,NUMOPTIONS);
  579.   clearmsg();
  580.   print1("Currently selected option is preceded by highlit >>");
  581.   print2("Move selected option with '>' and '<', ESCAPE to quit.");
  582.   do {
  583.     response = mcigetc();
  584.     switch(response) {
  585.     case 'j':
  586.     case '>':
  587. #ifdef KEY_DOWN
  588.     case KEY_DOWN:
  589. #endif
  590.       to = slot + 1;
  591. #ifndef COMPRESS_SAVE_FILES
  592.       if (to == 8)    /* COMPRESS_OPTION */
  593.     to = 9;
  594. #endif
  595. #if !defined(MSDOS) && !defined(AMIGA)
  596.       if (to == 9)    /* SHOW_COLOUR */
  597.     to = 10;
  598. #endif
  599.       slot = move_slot(slot,to,NUMOPTIONS+1);
  600.       break;
  601.     case 'k':
  602.     case '<':
  603. #ifdef KEY_UP
  604.     case KEY_UP:
  605. #endif
  606.       to = slot - 1;
  607. #if !defined(MSDOS) && !defined(AMIGA)
  608.       if (to == 9)    /* SHOW_COLOUR */
  609.     to = 8;
  610. #endif
  611. #ifndef COMPRESS_SAVE_FILES
  612.       if (to == 8)    /* COMPRESS_OPTION */
  613.     to = 7;
  614. #endif
  615.       if (to > 0)
  616.     slot = move_slot(slot,to,NUMOPTIONS+1); 
  617.       break;
  618. #ifdef KEY_HOME
  619.     case KEY_HOME:
  620.       slot = move_slot(slot,1,NUMOPTIONS+1);
  621.       break;
  622. #endif
  623. #ifdef KEY_LL
  624.     case KEY_LL:
  625.       slot = move_slot(slot,NUMOPTIONS,NUMOPTIONS+1);
  626.       break;
  627. #endif
  628.     case 't':
  629.       if (slot <= NUMTFOPTIONS) 
  630.     optionset(pow2(slot-1));
  631.       else if (slot == VERBOSITY_LEVEL)
  632.     Verbosity = TERSE;
  633.       else print3("'T' is meaningless for this option.");
  634.       break;
  635.     case 'f':
  636.       if (slot <= NUMTFOPTIONS) 
  637.     optionreset(pow2(slot-1));
  638.       else print3("'F' is meaningless for this option.");
  639.       break;
  640.     case 'm':
  641.       if (slot == VERBOSITY_LEVEL) 
  642.     Verbosity = MEDIUM;
  643.       else print3("'M' is meaningless for this option.");
  644.       break;
  645.     case 'v':
  646.       if (slot == VERBOSITY_LEVEL) 
  647.     Verbosity = VERBOSE;
  648.       else print3("'V' is meaningless for this option.");
  649.       break;
  650.     case '1':case '2':case '3':case '4':case '5':
  651.     case '6':case '7':case '8':case'9':
  652.       if (slot == SEARCH_DURATION)
  653.     Searchnum = response - '0';
  654.       else print3("A number is meaningless for this option.");
  655.       break;
  656.     case ESCAPE:
  657.       done = TRUE;
  658.       break;
  659.     default: print3("That response is meaningless for this option."); break;
  660.     }
  661.     display_option_slot(slot);
  662.     move_slot(slot,slot,NUMOPTIONS+1);
  663.   } while (! done);
  664.   if (optionp(SHOW_COLOUR))
  665.     colour_on();
  666.   else
  667.     colour_off();
  668. #if !defined(MSDOS) && !defined(AMIGA)
  669.   xredraw();
  670. #endif
  671. }
  672.  
  673.  
  674.  
  675. /* name an item */
  676. void callitem()
  677. {
  678.   int index;
  679.   pob obj;
  680.  
  681.   clearmsg();
  682.   setgamestatus(SKIP_MONSTERS);
  683.   print1("Call --");
  684.   index = getitem(NULL_ITEM);
  685.   if (index == CASHVALUE) print3("Can't rename cash!");
  686.   else if (index != ABORT) {
  687.     obj = Player.possessions[index];
  688.     if (obj->known)
  689.       print3("That item is already identified!");
  690.     else {
  691.       print1("Call it:");
  692.       obj->objstr = salloc(msgscanstring());
  693.       clearmsg();
  694.       print2("Also call all similar items by that name? [yn] ");
  695.       if (ynq2() == 'y') {
  696.     Objects[obj->id].objstr = obj->objstr;
  697.       }
  698.     }
  699.   }
  700. }
  701.       
  702.  
  703.  
  704.  
  705. /* open a door */
  706. void opendoor()
  707. {
  708.   int dir;
  709.   int ox,oy;
  710.  
  711.   clearmsg();
  712.   print1("Open --");
  713.   dir = getdir();
  714.   if (dir == ABORT)
  715.     setgamestatus(SKIP_MONSTERS);
  716.   else {
  717.     ox = Player.x + Dirs[0][dir];
  718.     oy = Player.y + Dirs[1][dir];
  719.     if (Level->site[ox][oy].locchar == OPEN_DOOR) {
  720.       print3("That door is already open!");
  721.       setgamestatus(SKIP_MONSTERS);
  722.     }
  723.     else if (Level->site[ox][oy].locchar == PORTCULLIS) {
  724.       print1("You try to lift the massive steel portcullis....");
  725.       if (random_range(100) < Player.str) {
  726.     print2("Incredible. You bust a gut and lift the portcullis.");
  727.     Level->site[ox][oy].locchar = FLOOR;
  728.     lset(ox, oy, CHANGED);
  729.       }
  730.       else {
  731.     print2("Argh. You ruptured yourself.");
  732.     p_damage(Player.str,UNSTOPPABLE,"a portcullis");
  733.       }
  734.     }
  735.     else if ((Level->site[ox][oy].locchar != CLOSED_DOOR) || 
  736.          loc_statusp(ox,oy,SECRET)) {
  737.       print3("You can't open that!");
  738.       setgamestatus(SKIP_MONSTERS);
  739.     }
  740.     else if (Level->site[ox][oy].aux == LOCKED) 
  741.       print3("That door seems to be locked.");
  742.     else {
  743.       Level->site[ox][oy].locchar = OPEN_DOOR;
  744.       lset(ox, oy, CHANGED);
  745.     }
  746.   }
  747. }
  748.  
  749.  
  750.  
  751. /* Try to destroy some location */
  752. void bash_location()
  753. {
  754.   int dir;
  755.   int ox,oy;
  756.  
  757.   clearmsg();
  758.   print1("Bashing --");
  759.   dir = getdir();
  760.   if (dir == ABORT)
  761.     setgamestatus(SKIP_MONSTERS);
  762.   else {
  763.     ox = Player.x + Dirs[0][dir];
  764.     oy = Player.y + Dirs[1][dir];
  765.     if ((Current_Environment == E_CITY) &&
  766.     (ox == 0) &&
  767.     (oy == 0)) {
  768.       print1("Back Door WIZARD Mode!");
  769.       print2("You will invalidate your score if you proceed.");
  770.       morewait();
  771.       print1("Enable WIZARD Mode? [yn] ");
  772.       if (ynq1()=='y') {
  773.     print2("You feel like a cheater.");
  774.     setgamestatus(CHEATED);
  775.       }
  776.       else print2("A sudden tension goes out of the air....");
  777.     }
  778.     else {
  779.       if (Level->site[ox][oy].locchar == WALL) {
  780.     print1("You hurl yourself at the wall!");
  781.     p_damage(Player.str,NORMAL_DAMAGE,"a suicidal urge");
  782.       }
  783.       else if (Level->site[ox][oy].locchar == OPEN_DOOR) {
  784.     print1("You hurl yourself through the open door!");
  785.     print2("Yaaaaah! ... thud.");
  786.     morewait();
  787.     Player.x = ox;
  788.     Player.y = oy;
  789.     p_damage(3,UNSTOPPABLE,"silliness");
  790.     p_movefunction(Level->site[Player.x][Player.y].p_locf);
  791.     setgamestatus(SKIP_MONSTERS); /* monsters are surprised... */
  792.       }
  793.       else if (Level->site[ox][oy].locchar == CLOSED_DOOR) {
  794.     if (loc_statusp(ox,oy,SECRET)) {
  795.       print1("You found a secret door!");
  796.       lreset(ox,oy,SECRET);
  797.       lset(ox, oy, CHANGED);
  798.     }
  799.     if (Level->site[ox][oy].aux == LOCKED) {
  800.       if (random_range(50+difficulty()*10) < Player.str) {
  801.         Player.x = ox;
  802.         Player.y = oy;
  803.         print2("You blast the door off its hinges!");
  804.         Level->site[ox][oy].locchar = FLOOR;
  805.         lset(ox, oy, CHANGED);
  806.         p_movefunction(Level->site[Player.x][Player.y].p_locf);
  807.         setgamestatus(SKIP_MONSTERS); /* monsters are surprised... */
  808.       }
  809.       else {
  810.         print1("Crash! The door holds.");
  811.         if (random_range(30) > Player.str)
  812.           p_damage(max(1,statmod(Player.str)),UNSTOPPABLE,"a door");
  813.       }
  814.     }
  815.     else {
  816.       Player.x = ox;
  817.       Player.y = oy;
  818.       print2("You bash open the door!");
  819.       if (random_range(30) > Player.str)
  820.         p_damage(1,UNSTOPPABLE,"a door");
  821.       Level->site[ox][oy].locchar = OPEN_DOOR;
  822.       lset(ox, oy, CHANGED);
  823.       p_movefunction(Level->site[Player.x][Player.y].p_locf);
  824.       setgamestatus(SKIP_MONSTERS); /* monsters are surprised... */
  825.     }
  826.       }
  827.       else if (Level->site[ox][oy].locchar == STATUE) {
  828.     statue_random(ox,oy);
  829.       }
  830.       else if (Level->site[ox][oy].locchar == PORTCULLIS) {
  831.     print1("Really, you don't have a prayer.");
  832.     if (random_range(1000) < Player.str) {
  833.       print2("The portcullis flies backwards into a thousand fragments.");
  834.       print3("Wow. What a stud.");
  835.       gain_experience(100);
  836.       Level->site[ox][oy].locchar = FLOOR;
  837.       Level->site[ox][oy].p_locf = L_NO_OP;
  838.       lset(ox, oy, CHANGED);
  839.     }
  840.     else {
  841.       print2("You only hurt yourself on the 3'' thick steel bars.");
  842.       p_damage(Player.str,UNSTOPPABLE,"a portcullis");
  843.     }
  844.       }
  845.       else if (Level->site[ox][oy].locchar == ALTAR) {
  846.     if ((Player.patron > 0)&&(Level->site[ox][oy].aux == Player.patron)) {
  847.       print1("You have a vision! An awesome angel hovers over the altar.");
  848.       print2("The angel says: 'You twit, don't bash your own altar!'");
  849.       print3("The angel slaps you upside the head for your presumption.");
  850.       p_damage(Player.hp-1,UNSTOPPABLE,"an annoyed angel");
  851.     }
  852.     else if (Level->site[ox][oy].aux == 0) {
  853.       print1("The feeble powers of the minor godling are not enough to");
  854.       print2("protect his altar! The altar crumbles away to dust.");
  855.       print3("You feel almost unbearably smug.");
  856.       Level->site[ox][oy].locchar = RUBBLE;
  857.       Level->site[ox][oy].p_locf = L_RUBBLE;
  858.       lset(ox, oy, CHANGED);
  859.       gain_experience(5);
  860.     }
  861.     else {
  862.       print1("You have successfully annoyed a major deity. Good job.");
  863.       print2("Zzzzap! A bolt of godsfire strikes!");
  864.       if (Player.rank[PRIESTHOOD] > 0) 
  865.         print3("Your own deity's aegis defends you from the bolt!");
  866.       p_damage(max(0,random_range(100)-Player.rank[PRIESTHOOD]*20),
  867.            UNSTOPPABLE,
  868.            "a bolt of godsfire");
  869.       if (Player.rank[PRIESTHOOD]*20+Player.pow+Player.level >
  870.           random_range(200)) {
  871.         morewait();
  872.         print1("The altar crumbles...");
  873.         Level->site[ox][oy].locchar = RUBBLE;
  874.         Level->site[ox][oy].p_locf = L_RUBBLE;
  875.         lset(ox, oy, CHANGED);
  876.         morewait();
  877.         if (Player.rank[PRIESTHOOD]) {
  878.           print2("You sense your deity's pleasure with you.");
  879.           morewait();
  880.           print3("You are surrounded by a golden glow.");
  881.           cleanse(1);
  882.           heal(10);
  883.         }
  884.         gain_experience(500);
  885.       }
  886.     }
  887.       }
  888.       else {
  889.     print3("You restrain yourself from total silliness.");
  890.     setgamestatus(SKIP_MONSTERS);
  891.       }
  892.     }
  893.   }
  894. }
  895.  
  896.  
  897. /* attempt destroy an item */
  898. void bash_item()
  899. {
  900.   int item;
  901.   pob obj;
  902.  
  903.   clearmsg();
  904.   print1("Destroy an item --");
  905.   item = getitem(NULL_ITEM);
  906.   if (item == CASHVALUE) print3("Can't destroy cash!");
  907.   else if (item != ABORT) {
  908.     obj = Player.possessions[item];
  909.     if (Player.str+random_range(20) > obj->fragility+random_range(20)) {
  910.       if (damage_item(obj) && Player.alignment < 0) {
  911.     print2("That was fun....");
  912.     gain_experience(obj->level * obj->level * 5);
  913.       }
  914.     }
  915.     else {
  916.       if (obj->objchar == WEAPON) {
  917.     print2("The weapon turned in your hand -- you hit yourself!");
  918.     p_damage(random_range(obj->dmg+abs(obj->plus)),
  919.          NORMAL_DAMAGE,
  920.          "a failure at vandalism");
  921.       }
  922.       else if (obj->objchar == ARTIFACT) {
  923.     print2("Uh Oh -- Now you've gotten it angry....");
  924.     p_damage(obj->level*10,
  925.          UNSTOPPABLE,
  926.          "an enraged artifact");
  927.       }
  928.       else {
  929.     print2("Ouch! Damn thing refuses to break...");
  930.     p_damage(1,UNSTOPPABLE,"a failure at vandalism");
  931.       }
  932.     }
  933.   }
  934. }
  935.  
  936.  
  937. /* guess what this does */
  938. /* if force is true, exiting due to some problem - don't bomb out */
  939. void save(compress, force)
  940. int compress, force;
  941. {
  942.   char fname[100];
  943.   int pos, ok = TRUE;
  944.  
  945.   clearmsg();
  946.   if (gamestatusp(ARENA_MODE)) {
  947.     if (force) {
  948.       resetgamestatus(ARENA_MODE);
  949.       change_environment(E_CITY);
  950.     }
  951.     else {
  952.       print3("Can't save the game in the arena!");
  953.       setgamestatus(SKIP_MONSTERS);
  954.       ok = FALSE;
  955.     }
  956.   }
  957.   else if (Current_Environment == E_ABYSS) {
  958.     if (force)
  959.       change_environment(E_COUNTRYSIDE);
  960.     else {
  961.       print3("Can't save the game in the Adept's Challenge!");
  962.       setgamestatus(SKIP_MONSTERS);
  963.       ok = FALSE;
  964.     }
  965.   }
  966.   else if (Current_Environment == E_TACTICAL_MAP) {
  967.     if (force)
  968.       change_environment(E_COUNTRYSIDE);
  969.     else {
  970.       print3("Can't save the game in the tactical map!");
  971.       setgamestatus(SKIP_MONSTERS);
  972.       ok = FALSE;
  973.     }
  974.   }
  975.   if (!force && ok) {
  976.     print1("Confirm Save? [yn] ");
  977.     ok = (ynq1() == 'y');
  978.   }
  979.   if (force || ok) {
  980.     print1("Enter savefile name: ");
  981.     strcpy(fname,msgscanstring());
  982.     if (fname[0] == '\0') {
  983.       print1("No save file entered - save aborted.");
  984.       ok = FALSE;
  985.     }
  986. #ifdef MSDOS
  987.     for (pos = 0; fname[pos] && isalnum(fname[pos]); pos++)
  988.       ;
  989. #else
  990.     for (pos = 0; fname[pos] && isprint(fname[pos]) && !isspace(fname[pos]);
  991.       pos++)
  992.       ;
  993. #endif
  994.     if (fname[pos]) {
  995.       sprintf(Str1, "Illegal character '%c' in filename - Save aborted.", fname[pos]);
  996.       print1(Str1);
  997.       ok = FALSE;
  998.     }
  999. #ifdef MSDOS
  1000.     if (strlen(fname) > 7)
  1001.     {
  1002.       print1("Save name longer than 7 characters - Save aborted.");
  1003.       ok = FALSE;
  1004.     }
  1005. #else
  1006. # ifdef SYSV
  1007.     if (strlen(fname) > 14 - EXT_LENGTH - 1)
  1008.     {
  1009.       sprintf(Str1, "Save name longer than %d characters - Save aborted.",
  1010.     14 - EXT_LENGTH - 1);
  1011.       print1(Str1);
  1012.       ok = FALSE;
  1013.     }
  1014. # endif
  1015. #endif
  1016.     if (ok)
  1017.       if (save_game(compress,fname)) {
  1018.     print3("Bye!");
  1019.     sleep(2);
  1020.     endgraf();
  1021.     exit(0);
  1022.       }
  1023.       else
  1024.     print1("Save Aborted.");
  1025.   }
  1026.   if (force) {
  1027.     morewait();
  1028.     clearmsg();
  1029.     print1("The game is quitting - you will lose your character.");
  1030.     print2("Try to save again? ");
  1031.     if (ynq2() == 'y')
  1032.       save(compress, force);
  1033.   }
  1034.   setgamestatus(SKIP_MONSTERS);    /* if we get here, we failed to save */
  1035. }
  1036.  
  1037. /* close a door */
  1038. void closedoor()
  1039. {
  1040.   int dir;
  1041.   int ox,oy;
  1042.  
  1043.   clearmsg();
  1044.  
  1045.   print1("Close --");
  1046.   dir = getdir();
  1047.   if (dir == ABORT)
  1048.     setgamestatus(SKIP_MONSTERS);
  1049.   else {
  1050.     ox = Player.x + Dirs[0][dir];
  1051.     oy = Player.y + Dirs[1][dir];
  1052.     if (Level->site[ox][oy].locchar == CLOSED_DOOR) {
  1053.       print3("That door is already closed!");
  1054.       setgamestatus(SKIP_MONSTERS);
  1055.     }
  1056.     else if (Level->site[ox][oy].locchar != OPEN_DOOR) {
  1057.       print3("You can't close that!");
  1058.       setgamestatus(SKIP_MONSTERS);
  1059.     }
  1060.     else Level->site[ox][oy].locchar = CLOSED_DOOR;
  1061.     lset(ox, oy, CHANGED);
  1062.   }
  1063. }
  1064.  
  1065. /* handle a h,j,k,l, etc. */
  1066. void moveplayer(dx,dy)
  1067. int dx,dy;
  1068. {
  1069.   if (p_moveable(Player.x+dx,Player.y+dy)) {
  1070.       
  1071.     if (Player.status[IMMOBILE] > 0) {
  1072.       resetgamestatus(FAST_MOVE);
  1073.       print3("You are unable to move");
  1074.     }
  1075.     else if ((Player.maxweight < Player.itemweight) && 
  1076.          random_range(2) &&
  1077.          (! Player.status[LEVITATING])) {
  1078.       if (gamestatusp(MOUNTED)) {
  1079.     print1("Your horse refuses to carry you and your pack another step!");
  1080.     print2("Your steed bucks wildly and throws you off!");
  1081.     p_damage(10,UNSTOPPABLE,"a cruelly abused horse");
  1082.     resetgamestatus(MOUNTED);
  1083.     summon(-1,HORSE);
  1084.       }
  1085.       else {
  1086.     p_damage(1,UNSTOPPABLE,"a rupture");
  1087.     print3("The weight of your pack drags you down. You can't move.");
  1088.       }
  1089.     }
  1090.     else {
  1091.       Player.x += dx;
  1092.       Player.y += dy;
  1093.       p_movefunction(Level->site[Player.x][Player.y].p_locf);
  1094.       
  1095.       /* causes moves to take effectively 30 seconds in town without
  1096.          monsters being sped up compared to player */
  1097.       if ((Current_Environment == E_CITY) ||
  1098.       (Current_Environment == E_VILLAGE)) {
  1099.     twiddle = ! twiddle;
  1100.     if (twiddle) {
  1101.       Time++;
  1102.       if (Time % 10 == 0) tenminute_check();
  1103.       else minute_status_check();
  1104.     }
  1105.       }
  1106.  
  1107.       /* this test protects against player entering countryside and still
  1108.       having effects from being on the Level, a kluge, but hey,... */
  1109.  
  1110.       if (Current_Environment != E_COUNTRYSIDE) {
  1111.     if (gamestatusp(FAST_MOVE))
  1112.       if ((Level->site[Player.x][Player.y].things != NULL) ||
  1113.           (optionp(RUNSTOP) && 
  1114.            loc_statusp(Player.x,Player.y,STOPS)))
  1115.         resetgamestatus(FAST_MOVE);
  1116.     if ((Level->site[Player.x][Player.y].things != NULL) &&
  1117.         (optionp(PICKUP)))
  1118.       pickup();
  1119.       }
  1120.     }
  1121.   }
  1122.   else if (gamestatusp(FAST_MOVE)) {
  1123.     drawvision(Player.x,Player.y);
  1124.     resetgamestatus(FAST_MOVE);
  1125.   }
  1126. }
  1127.  
  1128.  
  1129. /* handle a h,j,k,l, etc. */
  1130. void movepincountry(dx,dy)
  1131. int dx,dy;
  1132. {
  1133.   int i,takestime = TRUE;
  1134.   if ((Player.maxweight < Player.itemweight) && 
  1135.       random_range(2) &&
  1136.       (! Player.status[LEVITATING])) {
  1137.     if (gamestatusp(MOUNTED)) {
  1138.       print1("Your horse refuses to carry you and your pack another step!");
  1139.       print2("Your steed bucks wildly and throws you off!");
  1140.       p_damage(10,UNSTOPPABLE,"a cruelly abused horse");
  1141.       resetgamestatus(MOUNTED);
  1142.       morewait();
  1143.       print1("With a shrill neigh of defiance, your former steed gallops");
  1144.       print2("off into the middle distance....");
  1145.       if (Player.packptr != 0) {
  1146.     morewait();
  1147.     print1("You remember (too late) that the contents of your pack");
  1148.     print2("were kept in your steed's saddlebags!");
  1149.     for(i=0;i<MAXPACK;i++) {
  1150.       if (Player.pack[i] != NULL)
  1151.         free((char *) Player.pack[i]);
  1152.       Player.pack[i] = NULL;
  1153.     }
  1154.     Player.packptr = 0;
  1155.     calc_melee();
  1156.       }
  1157.     }
  1158.     else {
  1159.       p_damage(1,UNSTOPPABLE,"a rupture");
  1160.       print3("The weight of your pack drags you down. You can't move.");
  1161.     }
  1162.   }
  1163.   else {
  1164.     if (gamestatusp(LOST)) {
  1165.       print3("Being lost, you strike out randomly....");
  1166.       morewait();
  1167.       dx = random_range(3)-1;
  1168.       dy = random_range(3)-1;
  1169.     }
  1170.     if (p_country_moveable(Player.x+dx,Player.y+dy)) {
  1171.       if (Player.status[IMMOBILE] > 0) 
  1172.     print3("You are unable to move");
  1173.       else {
  1174.     Player.x += dx;
  1175.     Player.y += dy;
  1176.     if ((! gamestatusp(MOUNTED))&&(Player.possessions[O_BOOTS] != NULL)) {
  1177.       if (Player.possessions[O_BOOTS]->usef == I_BOOTS_7LEAGUE) {
  1178.         takestime = FALSE;
  1179.         if (Player.possessions[O_BOOTS]->blessing < 0) {
  1180.           print1("Whooah! -- Your boots launch you into the sky....");
  1181.           print2("You come down in a strange location....");
  1182.           Player.x = random_range(WIDTH);
  1183.           Player.y = random_range(LENGTH);
  1184.           morewait();
  1185.           clearmsg();
  1186.           print1("Your boots disintegrate with a malicious giggle...");
  1187.           dispose_lost_objects(1,Player.possessions[O_BOOTS]);
  1188.         }
  1189.         else if (Player.possessions[O_BOOTS]->known != 2) {
  1190.           print1("Wow! Your boots take you 7 leagues in a single stride!");
  1191.           Player.possessions[O_BOOTS]->known = 2;
  1192.         }
  1193.       }
  1194.     }
  1195.     if (gamestatusp(LOST) && (Precipitation < 1) &&
  1196.       c_statusp(Player.x, Player.y, SEEN)) {
  1197.       print3("Ah! Now you know where you are!");
  1198.       morewait();
  1199.       resetgamestatus(LOST);
  1200.     }
  1201.     else if (gamestatusp(LOST)) {
  1202.       print3("You're still lost.");
  1203.       morewait();
  1204.     }
  1205.     if (Precipitation > 0) Precipitation--;
  1206.     c_set(Player.x, Player.y, SEEN);
  1207.     terrain_check(takestime);
  1208.       }
  1209.     }
  1210.   }
  1211. }
  1212.  
  1213.